package deibay.server;

import java.util.Vector;
import java.util.logging.Level;

import deibay.DeibayLogger;
import deibay.datamodel.Category;
import deibay.datamodel.Item;
import deibay.datamodel.TreeCategory;
import deibay.messages.NotifyFinishBiddingDeadlineMsg;
import deibay.messages.NotifyNewBidderItemMsg;
import deibay.server.eventargs.SendMessageEventArg;
import deibay.server.events.BiddingItemEvent;
import deibay.server.events.Event;
import deibay.server.events.NewItemEvent;
import deibay.server.events.RemoveItemEvent;
import deibay.server.events.SendMessageEvent;
import deibay.server.events.SubscribeItemEvent;
import deibay.server.io.XmlDataBackup;


/**
 * @author   Joel Cordeiro
 */
public class DataManager implements EventConsumer{
	
	private TreeCategory categories = null;
	/**
	 * @uml.property  name="items"
	 */
	private Vector<Item> items = null;
	private Thread tClock;
	private Timer timer;
	private XmlDataBackup backup = null;
	
	public DataManager()
	{
		categories = new TreeCategory();
		items = new Vector<Item>();
		timer = new Timer(items);										
	}
	
	public void init()
	{			
		backup = new XmlDataBackup();
		backup.loadXmlRegister();
		for(Item item: backup.getItems())
			items.add(item);			
		initializeThreads();
		subscribeToEvents();
	}
	
	private void initializeThreads()
	{		

		tClock = new Thread(timer);
		tClock.start();	
	}
	
	private void subscribeToEvents()
	{
		ServerManager.getInstance().getEventManager().subscribe(this, BiddingItemEvent.class);
		ServerManager.getInstance().getEventManager().subscribe(this, SubscribeItemEvent.class);
		ServerManager.getInstance().getEventManager().subscribe(this, NewItemEvent.class);
		ServerManager.getInstance().getEventManager().subscribe(this, RemoveItemEvent.class);
	}
	
	public synchronized void addItem(Item p)
	{		
		synchronized (items)
		{
			backup.addProduct(p);
			this.items.add(p);		
			
			if(items.size() == 1)
			{		
				items.notifyAll();			
			}		
		}	
	}
	
	public synchronized void removeItem(Item p)
	{
		synchronized(items)
		{		
			items.remove(p);
			backup.removeProduct(p);

			while (items.isEmpty())
			{		
				try {
					items.wait();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}		
			}	
		}

	}

	public void addCategory(Category cat)
	{
		categories.addCategory(cat);
	}
	
	/**
	 * @return
	 * @uml.property  name="items"
	 */
	public Vector<Item> getItems()
	{
		return this.items;
	}
	
	public Vector<String> getItemsName()
	{
		Vector<String> itemsName = new Vector<String>();
		for(Item item: items)
		{
			itemsName.add(item.getName());
		}
		return itemsName;
	}
	
	public Item getItem(String id)
	{
		for(Item item: items)
		{
			if(item.getName().equals(id))
				return item;							
		}
		return null;
	}
	
	public Item getItemById(String id)
	{
		for(Item item: items)
		{
			if(item.getId().equals(id))
				return item;							
		}
		return null;
	}
	
	public synchronized Vector<String> getItemsBySeller(String seller)
	{	
		Vector<String> sellerItems = new Vector<String>();


		for(Item item: items)
		{
			if(item.getSeller().equals(seller))
			{
				sellerItems.add(item.getName());				
			}

		}		

		return sellerItems;
	}
	
	public void makeBackup()
	{
		
	}

	private synchronized void updateItem(String id, int value, String user)
	{

		for(Item item: items)
		{
			if(item.getId().equals(id))
			{
				item.setBidder(user);
				item.setPrice(value);
			}
		}

	}
	
	private synchronized void updateSubscribedUsersToItem(String user, String id)
	{
		synchronized(items)
		{
			for(Item item: items)
			{
				if(item.getId().equals(id))
					item.getSubscribedUsers().add(user);
			}
		}
	}
	
	public void handleEvent(Event event) {
		if(event instanceof BiddingItemEvent)
		{						
			String id = ((BiddingItemEvent)event).getBiddingItemEventArgs().getID();
			int value = ((BiddingItemEvent)event).getBiddingItemEventArgs().getValue();
			String user = ((BiddingItemEvent)event).getBiddingItemEventArgs().getUser().getId();
			Item item = getItemById(id);
			updateItem(id, value, user);
			backup.updateItem(id, value, user);
			NotifyNewBidderItemMsg msg = new NotifyNewBidderItemMsg("O utilizador "+user+" licitou o item '"+item.getName()+"' para o valor: "+value+" Euros");
			for(String subscribedUser: item.getSubscribedUsers())				
				ServerManager.getInstance().getEventManager().fireEvent(new SendMessageEvent(new SendMessageEventArg(subscribedUser, msg)));
		}
		else if(event instanceof SubscribeItemEvent)
		{
			SubscribeItemEvent subscribeEvent = (SubscribeItemEvent)event;
			updateSubscribedUsersToItem(subscribeEvent.getSubscribeItemEventArgs().getUser().getId(), subscribeEvent.getSubscribeItemEventArgs().getID());
			backup.updateSubscribedUsersToItem(subscribeEvent.getSubscribeItemEventArgs().getUser().getId(), subscribeEvent.getSubscribeItemEventArgs().getID());
		}	
		else if(event instanceof NewItemEvent)
		{
			NewItemEvent itemEvent = (NewItemEvent)event;
			addItem(itemEvent.getItemEventArgs().getItem());
		}
		else if(event instanceof RemoveItemEvent)
		{
			RemoveItemEvent removeEvent = (RemoveItemEvent)event;
			Item item = removeEvent.getRemoveItemEventArg().getItem();
			removeItem(item);
			String t = "O leilao "+item.toString()+" acabou. O licitador vencedor foi o  "+item.getBidder()+".";
			NotifyFinishBiddingDeadlineMsg msg = new NotifyFinishBiddingDeadlineMsg(t);
			for(String user: item.getSubscribedUsers())
				ServerManager.getInstance().getEventManager().fireEvent(new SendMessageEvent(new SendMessageEventArg(user, msg)));
		}
	}
	
}
